#include "mylexer.h"
#include <QDebug>
#include <QColor>
#include <QFont>
#include <Qsci/qsciscintilla.h>
#include <QSettings>
#include <QDir>

MyLexer::MyLexer(bool on, int nobg, QString color1, QString color2, QObject *parent)
    :QsciLexerCustom(parent),
      useStyle(on),
      darkColor(color1),
      lightColor(color2),
      ignoredColumns(nobg)
{
    defaultStyle = getStyle(MyStyleDefault);
    darkStyle = getStyle(MyStyleDark);
    lightStyle = getStyle(MyStyleLight);

    QDir::current().mkdir("conf");
    iniconf = new QSettings("./conf/lexer.ini", QSettings::IniFormat);
    readSettings(*iniconf);
    writeSettings(*iniconf);

    chars = (char *)malloc(chars_len);
    qDebug() << __FUNCTION__ << "init";
}

MyLexer::~MyLexer() {
    qDebug() << __FUNCTION__ << "deinit";
    free(chars);
    chars = NULL;

    delete iniconf;
}
const char *MyLexer::language() const {
    return "rawdata";
}

QString MyLexer::description(int style) const {
    switch (style) {
    case MyStyleDefault:
        return "MyStyleDefault";
    case MyStyleDark:
        return "MyStyleDark";
    case MyStyleLight:
        return "MyStyleLight";
    }

    return QString();
}

void MyLexer::styleText(int start, int end)
{
    QString source, line;

    if (!editor())
        return;

    qDebug() << "style text from " << start << end;

    if (end -start > chars_len) end = start + chars_len;

    if (end - start <= chars_len) {
        styleTextInner(start, end);
    }
    else {
        int section_size = editor()->lineLength(0) * dataHeight + blankLines;
        int pos1 = start, pos2 = start;
        for(;pos2 < end;) {
            pos2 = pos1 + section_size;
            if(pos2 > end) pos2 = end;

            styleTextInner(pos1, pos2);
            pos1 = pos2;
        }
    }

}
void MyLexer::styleTextInner(int start, int end) {
    qDebug() << "style text from " << start << end;

    if (!useStyle) {
        startStyling(start, 0x1f);
        setStyling(end - start, defaultStyle);
        return;
    }

    QString source, line;
    int i;

    editor()->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE, start, end, chars);

    source = QString(chars);

    startStyling(start, 0x1f);
    if (source.length()==1 && source.at(0) == '\n') {
        setStyling(1, defaultStyle);
        return;
    }

    QStringList list = source.split("\n");
    int realIgnoredColumns = m_ignoreColumnsOn ? ignoredColumns : 0;

    for (i = 0; i < list.size(); i++) {
        line = list.at(i);

        int lineLen = line.size();
        int nStyle = MyStyleDefault;
        int nLen = 0;
        int j = 0;
        int lineno= 0;

        QString linePrefix = line.left(line_header_len);
        if (linePrefix.length()==line_header_len) {
            lineno = linePrefix.mid(row_number_start, row_number_len).toInt();
            if (lineStyledMap.value(linePrefix)) continue;
        }

        for (; j < lineLen; ) {
            if (nStyle == MyStyleDefault ) {
                nLen = line_header_len + realIgnoredColumns * (dataSize+1);
                if (j + nLen > lineLen) nLen = lineLen - j;

                setStyling(nLen, defaultStyle);

                nStyle = MyStyleDark + lineno % 2;
                j += nLen;

            } else if (nStyle == MyStyleDark) {
                nLen = 4 * (dataSize+1);
                if (j + nLen > lineLen) nLen = lineLen - j;

                setStyling(nLen, darkStyle);


                nStyle = MyStyleLight;
                j += nLen;

            } else if (nStyle == MyStyleLight) {
                nLen = 4 * (dataSize+1);
                if (j + nLen > lineLen) nLen = lineLen - j;

                setStyling(nLen, lightStyle);

                nStyle = MyStyleDark;
                j += nLen;
            }
        }

        if ((i < list.size()-1)){ // is a full line

            setStyling(1, defaultStyle);
        }
//        if (linePrefix.length() > 0)
//            lineStyledMap.insert(linePrefix, true);
    }

}

// QColor MyLexer::defaultColor(int style) const
//{
//     switch(style){
//     case MyStyleDefault:
//         return QColor(0x0, 0x0, 0x0);
//     case MyStyleDark:
//         return QColor(0xff, 0xff, 0xff);
//     case MyStyleLight:
//         return QColor(0xff, 0xff, 0xff);
//     }
//     return QsciLexer::defaultColor(style);
// }

QFont MyLexer::defaultFont(int style) const {
    Q_UNUSED(style);
    QFont codefont("Source Code Pro");
    codefont.setPointSize(12);
    return codefont;
}

QColor MyLexer::defaultPaper(int style) const {

    switch (style) {
    case MyStyleDefault:
        return QColor(0xff, 0xff, 0xff);
    case MyStyleDark:
        return QColor(darkColor);
    case MyStyleLight:
        return QColor(lightColor);
    }
    return QsciLexer::defaultPaper(style);
}

void MyLexer::setIgnoredColumns(int val) {
    ignoredColumns = val;
}

void MyLexer::setBGColor(QString colorname1, QString colorname2) {
    darkColor = colorname1;
    lightColor = colorname2;

    darkStyle = getStyle(MyStyleDark);
    lightStyle = getStyle(MyStyleLight);

    int color1 = colorname1.mid(1).toInt(NULL, 16);
    int color2 = colorname2.mid(1).toInt(NULL, 16);
    iniconf->setValue("Scintilla/rawdata/style1/paper", color1);
    iniconf->setValue("Scintilla/rawdata/style2/paper", color2);
    iniconf->sync();

    readSettings(*iniconf);

}

void MyLexer::setEnabled(bool on)
{
    useStyle = on;
}

void MyLexer::setIgnoreColumnsOn(bool on)
{
    m_ignoreColumnsOn = on;
}

void MyLexer::clearStyleMap()
{
    lineStyledMap.clear();
}

QsciStyle MyLexer::getStyle(int style) {
    if (style < MaxStyle) {
        return QsciStyle(style, description(style), defaultColor(style),
                         defaultPaper(style), defaultFont(style));
    } else {
        return QsciStyle(style);
    }
}
